use super::{
    buf::Buf, cfg::Cfg, err, err_value, json, selbox::SelBox, task::Task, throw_err, Base, Client,
    ECode, MapSv, RNull, Resp, TBase, VBase, VMap, Value,
};

pub struct Ground;

impl Base for Ground {}
impl TBase for Ground {}

impl Ground {
    pub async fn do_free(&self, para: &Value, client: &Client) -> Resp {
        let para = para.ckobj()?;
        let data = para.ck_obj("v")?;

        let line = data.ck_str("line")?;
        let sel_sn = data.ck_str("sel")?;
        let tp = data.ck_str("tp")?;

        let cfg = Cfg::new(line, sel_sn);
        let cfg = cfg.get(client).await?;

        let buf = Buf::new(line, sel_sn, None);
        let mut task = Task::new(line, sel_sn);

        task.ck(tp, &data, &buf, &cfg, client).await
    }

    pub async fn do_inbuf(&self, para: &MapSv, client: &Client) -> RNull {
        let data = para.ck_obj("v")?;

        let line = data.ck_str("line")?;
        let sel_sn = data.ck_str("sel")?;
        let sn = data.ck_str("sn")?;
        let tp = data.ck_str("tp")?;

        let selbox = SelBox::new(line, sel_sn);
        let buf = Buf::new(line, sel_sn, None);

        let (boxsn, pos) = match tp {
            "inner" => selbox.empty_inner(&buf, client).await?,
            "outer" => selbox.empty_outer(&buf, client).await?,
            _ => throw_err!(ECode::Para, "tp error"),
        };

        let val = json!({
            "sn": sn,
            "box": boxsn,
            "to": pos,
        });

        buf.put(tp, val, client).await?;

        Ok(())
    }

    pub async fn do_idle(&self, para: &MapSv, client: &Client) -> RNull {
        let data = para.ck_obj("v")?;

        let line = data.ck_str("line")?;
        let sel_sn = data.ck_str("sel")?;

        let cfg = Cfg::new(line, sel_sn);
        let cfg = cfg.get(client).await?;

        let cmd = json!({ "line": line, "sel": sel_sn });

        let body = client.real(&cmd, "select/pair").await?;
        let body = body.ck_array("data")?;

        let mut task = Task::new(line, sel_sn);

        for d in body.iter() {
            let d = d.ckobj()?;
            let _ = task.put(d, &cfg, client).await;
        }

        Ok(())
    }
}
